"""
性能监控器

提供系统性能、交易性能、策略性能等监控功能。
"""

from typing import Dict, List, Optional, Any
from datetime import datetime, timedelta
from dataclasses import dataclass, field
import asyncio
import psutil
import time
from decimal import Decimal

from .monitor import BaseMonitor, MonitorConfig, MonitorType, MonitorMetrics, MonitorLevel


@dataclass
class PerformanceMetrics:
    """性能指标"""
    timestamp: datetime = field(default_factory=datetime.now)
    
    # 系统性能指标
    cpu_usage: float = 0.0  # CPU使用率
    memory_usage: float = 0.0  # 内存使用率
    disk_usage: float = 0.0  # 磁盘使用率
    network_io: Dict[str, float] = field(default_factory=dict)  # 网络IO
    
    # 应用性能指标
    response_time: float = 0.0  # 响应时间
    throughput: float = 0.0  # 吞吐量
    error_rate: float = 0.0  # 错误率
    active_connections: int = 0  # 活跃连接数
    
    # 交易性能指标
    order_latency: float = 0.0  # 订单延迟
    execution_time: float = 0.0  # 执行时间
    fill_rate: float = 0.0  # 成交率
    slippage: float = 0.0  # 滑点
    
    # 策略性能指标
    total_return: float = 0.0  # 总收益率
    sharpe_ratio: float = 0.0  # 夏普比率
    max_drawdown: float = 0.0  # 最大回撤
    win_rate: float = 0.0  # 胜率
    
    # 自定义指标
    custom_metrics: Dict[str, Any] = field(default_factory=dict)


class SystemPerformanceMonitor(BaseMonitor):
    """系统性能监控器"""
    
    def __init__(self, config: Optional[MonitorConfig] = None):
        """初始化系统性能监控器"""
        if config is None:
            config = MonitorConfig(
                monitor_id="system_performance",
                monitor_type=MonitorType.PERFORMANCE,
                name="系统性能监控",
                description="监控CPU、内存、磁盘、网络等系统资源使用情况",
                interval=5.0
            )
        super().__init__(config)
        
        # 历史数据
        self._cpu_history: List[float] = []
        self._memory_history: List[float] = []
        self._last_network_io: Optional[Dict[str, int]] = None
    
    async def check(self) -> MonitorMetrics:
        """检查系统性能"""
        try:
            # CPU使用率
            cpu_usage = psutil.cpu_percent(interval=1)
            self._cpu_history.append(cpu_usage)
            if len(self._cpu_history) > 60:  # 保留最近60个数据点
                self._cpu_history.pop(0)
            
            # 内存使用率
            memory = psutil.virtual_memory()
            memory_usage = memory.percent
            self._memory_history.append(memory_usage)
            if len(self._memory_history) > 60:
                self._memory_history.pop(0)
            
            # 磁盘使用率
            disk = psutil.disk_usage('/')
            disk_usage = (disk.used / disk.total) * 100
            
            # 网络IO
            network_io = {}
            net_io = psutil.net_io_counters()
            if self._last_network_io:
                bytes_sent_per_sec = net_io.bytes_sent - self._last_network_io['bytes_sent']
                bytes_recv_per_sec = net_io.bytes_recv - self._last_network_io['bytes_recv']
                network_io = {
                    'bytes_sent_per_sec': bytes_sent_per_sec / self.config.interval,
                    'bytes_recv_per_sec': bytes_recv_per_sec / self.config.interval
                }
            
            self._last_network_io = {
                'bytes_sent': net_io.bytes_sent,
                'bytes_recv': net_io.bytes_recv
            }
            
            # 创建性能指标
            perf_metrics = PerformanceMetrics(
                cpu_usage=cpu_usage,
                memory_usage=memory_usage,
                disk_usage=disk_usage,
                network_io=network_io
            )
            
            # 更新监控指标
            metrics = MonitorMetrics(self.config.monitor_id)
            metrics.update_metrics({
                'cpu_usage': cpu_usage,
                'memory_usage': memory_usage,
                'disk_usage': disk_usage,
                'network_io': network_io,
                'cpu_avg_5min': sum(self._cpu_history) / len(self._cpu_history) if self._cpu_history else 0,
                'memory_avg_5min': sum(self._memory_history) / len(self._memory_history) if self._memory_history else 0
            })
            
            # 检查阈值告警
            await self._check_thresholds(perf_metrics)
            
            return metrics
            
        except Exception as e:
            self._emit_event(
                "performance_check_error",
                MonitorLevel.ERROR,
                f"系统性能检查失败: {e}"
            )
            return MonitorMetrics(self.config.monitor_id)
    
    async def _check_thresholds(self, perf_metrics: PerformanceMetrics) -> None:
        """检查性能阈值"""
        # CPU使用率告警
        cpu_threshold = self.config.thresholds.get('cpu_usage', 80.0)
        if perf_metrics.cpu_usage > cpu_threshold:
            self._emit_event(
                "high_cpu_usage",
                MonitorLevel.WARNING,
                f"CPU使用率过高: {perf_metrics.cpu_usage:.1f}%",
                {"cpu_usage": perf_metrics.cpu_usage, "threshold": cpu_threshold}
            )
        
        # 内存使用率告警
        memory_threshold = self.config.thresholds.get('memory_usage', 85.0)
        if perf_metrics.memory_usage > memory_threshold:
            self._emit_event(
                "high_memory_usage",
                MonitorLevel.WARNING,
                f"内存使用率过高: {perf_metrics.memory_usage:.1f}%",
                {"memory_usage": perf_metrics.memory_usage, "threshold": memory_threshold}
            )
        
        # 磁盘使用率告警
        disk_threshold = self.config.thresholds.get('disk_usage', 90.0)
        if perf_metrics.disk_usage > disk_threshold:
            self._emit_event(
                "high_disk_usage",
                MonitorLevel.WARNING,
                f"磁盘使用率过高: {perf_metrics.disk_usage:.1f}%",
                {"disk_usage": perf_metrics.disk_usage, "threshold": disk_threshold}
            )


class TradingPerformanceMonitor(BaseMonitor):
    """交易性能监控器"""
    
    def __init__(self, config: Optional[MonitorConfig] = None):
        """初始化交易性能监控器"""
        if config is None:
            config = MonitorConfig(
                monitor_id="trading_performance",
                monitor_type=MonitorType.TRADING,
                name="交易性能监控",
                description="监控订单延迟、执行时间、成交率等交易性能指标",
                interval=10.0
            )
        super().__init__(config)
        
        # 性能数据收集
        self._order_latencies: List[float] = []
        self._execution_times: List[float] = []
        self._fill_rates: List[float] = []
        self._slippages: List[float] = []
    
    async def check(self) -> MonitorMetrics:
        """检查交易性能"""
        try:
            # 计算平均指标
            avg_order_latency = sum(self._order_latencies) / len(self._order_latencies) if self._order_latencies else 0
            avg_execution_time = sum(self._execution_times) / len(self._execution_times) if self._execution_times else 0
            avg_fill_rate = sum(self._fill_rates) / len(self._fill_rates) if self._fill_rates else 0
            avg_slippage = sum(self._slippages) / len(self._slippages) if self._slippages else 0
            
            # 创建性能指标
            perf_metrics = PerformanceMetrics(
                order_latency=avg_order_latency,
                execution_time=avg_execution_time,
                fill_rate=avg_fill_rate,
                slippage=avg_slippage
            )
            
            # 更新监控指标
            metrics = MonitorMetrics(self.config.monitor_id)
            metrics.update_metrics({
                'avg_order_latency': avg_order_latency,
                'avg_execution_time': avg_execution_time,
                'avg_fill_rate': avg_fill_rate,
                'avg_slippage': avg_slippage,
                'total_orders': len(self._order_latencies),
                'max_order_latency': max(self._order_latencies) if self._order_latencies else 0,
                'min_order_latency': min(self._order_latencies) if self._order_latencies else 0
            })
            
            # 检查性能阈值
            await self._check_trading_thresholds(perf_metrics)
            
            return metrics
            
        except Exception as e:
            self._emit_event(
                "trading_performance_check_error",
                MonitorLevel.ERROR,
                f"交易性能检查失败: {e}"
            )
            return MonitorMetrics(self.config.monitor_id)
    
    def record_order_latency(self, latency: float) -> None:
        """记录订单延迟"""
        self._order_latencies.append(latency)
        if len(self._order_latencies) > 1000:  # 保留最近1000个数据点
            self._order_latencies.pop(0)
    
    def record_execution_time(self, execution_time: float) -> None:
        """记录执行时间"""
        self._execution_times.append(execution_time)
        if len(self._execution_times) > 1000:
            self._execution_times.pop(0)
    
    def record_fill_rate(self, fill_rate: float) -> None:
        """记录成交率"""
        self._fill_rates.append(fill_rate)
        if len(self._fill_rates) > 1000:
            self._fill_rates.pop(0)
    
    def record_slippage(self, slippage: float) -> None:
        """记录滑点"""
        self._slippages.append(slippage)
        if len(self._slippages) > 1000:
            self._slippages.pop(0)
    
    async def _check_trading_thresholds(self, perf_metrics: PerformanceMetrics) -> None:
        """检查交易性能阈值"""
        # 订单延迟告警
        latency_threshold = self.config.thresholds.get('order_latency', 100.0)  # 100ms
        if perf_metrics.order_latency > latency_threshold:
            self._emit_event(
                "high_order_latency",
                MonitorLevel.WARNING,
                f"订单延迟过高: {perf_metrics.order_latency:.2f}ms",
                {"order_latency": perf_metrics.order_latency, "threshold": latency_threshold}
            )
        
        # 成交率告警
        fill_rate_threshold = self.config.thresholds.get('fill_rate', 0.95)  # 95%
        if perf_metrics.fill_rate < fill_rate_threshold:
            self._emit_event(
                "low_fill_rate",
                MonitorLevel.WARNING,
                f"成交率过低: {perf_metrics.fill_rate:.2%}",
                {"fill_rate": perf_metrics.fill_rate, "threshold": fill_rate_threshold}
            )
        
        # 滑点告警
        slippage_threshold = self.config.thresholds.get('slippage', 0.001)  # 0.1%
        if perf_metrics.slippage > slippage_threshold:
            self._emit_event(
                "high_slippage",
                MonitorLevel.WARNING,
                f"滑点过高: {perf_metrics.slippage:.4%}",
                {"slippage": perf_metrics.slippage, "threshold": slippage_threshold}
            )


class StrategyPerformanceMonitor(BaseMonitor):
    """策略性能监控器"""
    
    def __init__(self, config: Optional[MonitorConfig] = None):
        """初始化策略性能监控器"""
        if config is None:
            config = MonitorConfig(
                monitor_id="strategy_performance",
                monitor_type=MonitorType.PERFORMANCE,
                name="策略性能监控",
                description="监控策略收益率、夏普比率、最大回撤等性能指标",
                interval=60.0
            )
        super().__init__(config)
        
        # 策略性能数据
        self._returns: List[float] = []
        self._portfolio_values: List[float] = []
        self._trades: List[Dict[str, Any]] = []
    
    async def check(self) -> MonitorMetrics:
        """检查策略性能"""
        try:
            # 计算性能指标
            total_return = self._calculate_total_return()
            sharpe_ratio = self._calculate_sharpe_ratio()
            max_drawdown = self._calculate_max_drawdown()
            win_rate = self._calculate_win_rate()
            
            # 创建性能指标
            perf_metrics = PerformanceMetrics(
                total_return=total_return,
                sharpe_ratio=sharpe_ratio,
                max_drawdown=max_drawdown,
                win_rate=win_rate
            )
            
            # 更新监控指标
            metrics = MonitorMetrics(self.config.monitor_id)
            metrics.update_metrics({
                'total_return': total_return,
                'sharpe_ratio': sharpe_ratio,
                'max_drawdown': max_drawdown,
                'win_rate': win_rate,
                'total_trades': len(self._trades),
                'avg_return': sum(self._returns) / len(self._returns) if self._returns else 0,
                'volatility': self._calculate_volatility()
            })
            
            # 检查策略性能阈值
            await self._check_strategy_thresholds(perf_metrics)
            
            return metrics
            
        except Exception as e:
            self._emit_event(
                "strategy_performance_check_error",
                MonitorLevel.ERROR,
                f"策略性能检查失败: {e}"
            )
            return MonitorMetrics(self.config.monitor_id)
    
    def record_return(self, return_value: float) -> None:
        """记录收益率"""
        self._returns.append(return_value)
        if len(self._returns) > 10000:  # 保留最近10000个数据点
            self._returns.pop(0)
    
    def record_portfolio_value(self, value: float) -> None:
        """记录组合价值"""
        self._portfolio_values.append(value)
        if len(self._portfolio_values) > 10000:
            self._portfolio_values.pop(0)
    
    def record_trade(self, trade: Dict[str, Any]) -> None:
        """记录交易"""
        self._trades.append(trade)
        if len(self._trades) > 10000:
            self._trades.pop(0)
    
    def _calculate_total_return(self) -> float:
        """计算总收益率"""
        if len(self._portfolio_values) < 2:
            return 0.0
        
        initial_value = self._portfolio_values[0]
        current_value = self._portfolio_values[-1]
        
        if initial_value == 0:
            return 0.0
        
        return (current_value - initial_value) / initial_value
    
    def _calculate_sharpe_ratio(self) -> float:
        """计算夏普比率"""
        if len(self._returns) < 2:
            return 0.0
        
        avg_return = sum(self._returns) / len(self._returns)
        volatility = self._calculate_volatility()
        
        if volatility == 0:
            return 0.0
        
        # 假设无风险利率为0
        return avg_return / volatility
    
    def _calculate_volatility(self) -> float:
        """计算波动率"""
        if len(self._returns) < 2:
            return 0.0
        
        avg_return = sum(self._returns) / len(self._returns)
        variance = sum((r - avg_return) ** 2 for r in self._returns) / len(self._returns)
        
        return variance ** 0.5
    
    def _calculate_max_drawdown(self) -> float:
        """计算最大回撤"""
        if len(self._portfolio_values) < 2:
            return 0.0
        
        peak = self._portfolio_values[0]
        max_drawdown = 0.0
        
        for value in self._portfolio_values[1:]:
            if value > peak:
                peak = value
            else:
                drawdown = (peak - value) / peak if peak > 0 else 0
                max_drawdown = max(max_drawdown, drawdown)
        
        return max_drawdown
    
    def _calculate_win_rate(self) -> float:
        """计算胜率"""
        if not self._trades:
            return 0.0
        
        winning_trades = sum(1 for trade in self._trades if trade.get('pnl', 0) > 0)
        return winning_trades / len(self._trades)
    
    async def _check_strategy_thresholds(self, perf_metrics: PerformanceMetrics) -> None:
        """检查策略性能阈值"""
        # 最大回撤告警
        max_drawdown_threshold = self.config.thresholds.get('max_drawdown', 0.1)  # 10%
        if perf_metrics.max_drawdown > max_drawdown_threshold:
            self._emit_event(
                "high_drawdown",
                MonitorLevel.WARNING,
                f"最大回撤过高: {perf_metrics.max_drawdown:.2%}",
                {"max_drawdown": perf_metrics.max_drawdown, "threshold": max_drawdown_threshold}
            )
        
        # 夏普比率告警
        min_sharpe_threshold = self.config.thresholds.get('min_sharpe_ratio', 1.0)
        if perf_metrics.sharpe_ratio < min_sharpe_threshold:
            self._emit_event(
                "low_sharpe_ratio",
                MonitorLevel.WARNING,
                f"夏普比率过低: {perf_metrics.sharpe_ratio:.2f}",
                {"sharpe_ratio": perf_metrics.sharpe_ratio, "threshold": min_sharpe_threshold}
            )
        
        # 胜率告警
        min_win_rate_threshold = self.config.thresholds.get('min_win_rate', 0.4)  # 40%
        if perf_metrics.win_rate < min_win_rate_threshold:
            self._emit_event(
                "low_win_rate",
                MonitorLevel.WARNING,
                f"胜率过低: {perf_metrics.win_rate:.2%}",
                {"win_rate": perf_metrics.win_rate, "threshold": min_win_rate_threshold}
            )


class PerformanceMonitor:
    """
    性能监控器管理器
    
    管理和协调各种性能监控器。
    """
    
    def __init__(self):
        """初始化性能监控器管理器"""
        self.system_monitor = SystemPerformanceMonitor()
        self.trading_monitor = TradingPerformanceMonitor()
        self.strategy_monitor = StrategyPerformanceMonitor()
        
        self._monitors = {
            'system': self.system_monitor,
            'trading': self.trading_monitor,
            'strategy': self.strategy_monitor
        }
    
    def start_all(self) -> None:
        """启动所有性能监控器"""
        for monitor in self._monitors.values():
            monitor.start()
    
    def stop_all(self) -> None:
        """停止所有性能监控器"""
        for monitor in self._monitors.values():
            monitor.stop()
    
    def get_performance_summary(self) -> Dict[str, Any]:
        """获取性能摘要"""
        summary = {}
        
        for name, monitor in self._monitors.items():
            summary[name] = {
                'status': monitor.status.value,
                'metrics': monitor.metrics.metrics,
                'last_check': monitor.last_check_time.isoformat() if monitor.last_check_time else None,
                'check_count': monitor.check_count,
                'error_count': monitor.error_count
            }
        
        return summary
    
    def record_trading_metrics(
        self,
        order_latency: Optional[float] = None,
        execution_time: Optional[float] = None,
        fill_rate: Optional[float] = None,
        slippage: Optional[float] = None
    ) -> None:
        """记录交易性能指标"""
        if order_latency is not None:
            self.trading_monitor.record_order_latency(order_latency)
        if execution_time is not None:
            self.trading_monitor.record_execution_time(execution_time)
        if fill_rate is not None:
            self.trading_monitor.record_fill_rate(fill_rate)
        if slippage is not None:
            self.trading_monitor.record_slippage(slippage)
    
    def record_strategy_metrics(
        self,
        return_value: Optional[float] = None,
        portfolio_value: Optional[float] = None,
        trade: Optional[Dict[str, Any]] = None
    ) -> None:
        """记录策略性能指标"""
        if return_value is not None:
            self.strategy_monitor.record_return(return_value)
        if portfolio_value is not None:
            self.strategy_monitor.record_portfolio_value(portfolio_value)
        if trade is not None:
            self.strategy_monitor.record_trade(trade)